﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace Xant.Querier.Core
{
    /// <summary>
    /// 条件对
    /// </summary>
    /// <remarks>使用逻辑操作符(AND/OR)连接两个条件</remarks>
    public class CriteriaPair: Xpression
    {
        public LogicalOperator Operator { get; set; }
        public Xpression Left { get; set; }
        public Xpression Right { get; set; }

        public CriteriaPair(Xpression left, LogicalOperator operatr, Xpression right)
        {
            if (left == null)
            {
                throw new ArgumentNullException("left", "一个条件对必须至少拥有一个左分支条件。");
            }
            this.Left = left;
            this.Operator = operatr;
            this.Right = right;
        }

        /// <summary>
        /// 左子条件运算符优先级是否比此算式本身的运算符优先级低
        /// </summary>
        public bool LeftExpressionOperatorIsLower
        {
            get
            {
                if (!(Left is CriteriaPair))
                    return false;
                return (Left as CriteriaPair).Operator.IsLowerPriorityThan(this.Operator);
            }
        }

        /// <summary>
        /// 右子条件运算符优先级是否比此算式本身的运算符优先级低
        /// </summary>
        public bool RightExpressionOperatorIsLower
        {
            get
            {
                if (!(Right is CriteriaPair))
                    return false;
                return (Right as CriteriaPair).Operator.IsLowerPriorityThan(this.Operator);
            }
        }

        public override string ToString()
        {
            var left = "{0}";
            var right = "{2}";
            if (this.LeftExpressionOperatorIsLower)//如果左表达式为条件对，且算式运算符优先级较低，则用括号包围
            {
                left = "(" + left + ")";
            }
            if (this.RightExpressionOperatorIsLower)//如果右表达式为条件对，且算式运算符优先级较低，则用括号包围
            {
                right = "(" + right + ")";
            }
            string format = left + " {1} " + right;
            return string.Format(format, this.Left, this.Operator.ToString().ToUpper(), this.Right);
        }
    }
}
